<template>
    <div>
      <!-- 子组件模板 -->
      <h3>子组件</h3>
      <div>
        <p>子组件可以注入父组件提供的数据：</p>
        <p>消息: {{ message }}</p>
        <p>计数: {{ count }}</p>
        
        <div class="controls">
          <button @click="updateParentMessage">更新父组件消息</button>
        </div>
        
        <!-- 引入孙组件 -->
        <Grandson />
      </div>
    </div>
  </template>
  
  <script lang="ts" setup>
  /**
   * Provide/Inject 详解 - 中间组件
   * 
   * 1. 中间组件的角色：
   *    - 可以同时是数据的消费者（通过inject）和提供者（通过provide）
   *    - 可以选择是否使用祖先提供的数据
   *    - 可以修改或包装祖先提供的数据，然后提供给自己的后代
   * 
   * 2. 数据传递：
   *    - 中间组件不需要显式传递数据给后代组件
   *    - 后代组件可以直接从最近的提供者注入数据
   */
  
  import { inject } from 'vue';
  import Grandson from './grandson.vue';
  
  /**
   * 3. 注入数据 (Inject)：
   * 
   * 3.1 基本注入：
   *     const value = inject('key');
   * 
   * 3.2 带默认值的注入：
   *     const value = inject('key', 'default value');
   * 
   * 3.3 注入函数：
   *     const updateFn = inject('updateFunction');
   * 
   * 3.4 使用工厂函数作为默认值：
   *     const value = inject('key', () => createExpensiveValue());
   */
  
  // 注入父组件提供的数据
  const message = inject('message', '默认消息');  // 注入响应式数据
  const count = inject('count', 0);               // 注入响应式数据
  
  // 注入父组件提供的方法
  const updateMessage = inject('updateMessage', () => {});
  
  // 使用注入的方法更新父组件数据
  function updateParentMessage() {
    updateMessage();
  }
  
  /**
   * 4. 重新提供 (Re-providing)：
   *    - 组件可以注入数据，然后修改或包装后重新提供给后代
   *    - 这种模式可以用于创建作用域隔离或添加中间层处理
   * 
   * 示例：
   * const theme = inject('theme');
   * provide('theme', {
   *   ...theme,
   *   // 添加或修改某些属性
   *   fontSize: 'larger'
   * });
   */
  
  // 这里没有重新提供数据，孙组件将直接从父组件注入数据
  </script>
  
  <style scoped>
  /* 子组件样式 */
  div {
    background: linear-gradient(to right, #f6d365, #fda085);
    border-radius: 12px;
    padding: 20px;
    margin: 15px 0;
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
    transition: all 0.3s ease;
  }
  
  div:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
  }
  
  h3 {
    color: #ffffff;
    font-size: 22px;
    margin-bottom: 15px;
    text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.2);
    font-weight: 500;
    letter-spacing: 1px;
  }

  p {
    margin: 8px 0;
    color: white;
  }

  .controls {
    margin: 15px 0;
  }

  button {
    background-color: white;
    color: #ff7e5f;
    border: none;
    padding: 8px 15px;
    border-radius: 6px;
    font-weight: bold;
    cursor: pointer;
    transition: all 0.2s;
  }

  button:hover {
    background-color: #ff7e5f;
    color: white;
    transform: translateY(-2px);
  }
  </style>